package com.zx.notification.producer.listener;

import com.zx.notification.common.constants.NotificationConstants;
import com.zx.notification.common.event.ConfigReloadEvent;
import com.zx.redis.block.service.RedisBlockService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.Set;

/**
 * 模板配置变更监听器
 * 监听模板配置变更事件，清理相关缓存
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TemplateConfigChangeListener {

    private final RedisBlockService redisBlockService;

    /**
     * 处理配置重载事件
     * 当收到模板相关的配置变更事件时，清理模板缓存
     *
     * @param event 配置重载事件
     */
    @EventListener
    public void handleConfigReloadEvent(ConfigReloadEvent event) {
        try {
            // 检查是否是模板配置变更
            if ("template".equals(event.getConfigType())) {
                log.info("收到模板配置变更事件: {}", event.getMessage());

                // 如果是特定模板变更，则只清理该模板的缓存
                String message = event.getMessage();
                if (message != null && message.startsWith("template_code:")) {
                    String templateCode = message.substring("template_code:".length());
                    String cacheKey = NotificationConstants.RedisCache.TEMPLATE_CACHE_KEY_PREFIX + templateCode;
                    redisBlockService.deleteObject(cacheKey);
                    log.info("已清理模板[{}]的缓存", templateCode);
                } else {
                    // 如果是全局模板配置变更，则清理所有模板缓存
                    clearAllTemplateCache();
                }
            }
        } catch (Exception e) {
            log.error("处理模板配置变更事件时发生错误", e);
        }
    }

    /**
     * 清空所有模板缓存
     */
    @SuppressWarnings("unchecked")
    private void clearAllTemplateCache() {
        try {
            // 使用scan命令查找所有匹配的缓存键
            Set<String> keys = (Set<String>) redisBlockService.redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
                Set<String> result = new HashSet<>();

                // 使用scan命令扫描所有匹配模板缓存键前缀的键
                // match: 匹配以TEMPLATE_CACHE_KEY_PREFIX开头的所有键
                // count: 每次迭代返回的元素数量，设置为1000以提高扫描效率
                Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions()
                        .match(NotificationConstants.RedisCache.TEMPLATE_CACHE_KEY_PREFIX + "*")
                        .count(1000)
                        .build());

                while (cursor.hasNext()) {
                    result.add(new String(cursor.next()));
                }
                cursor.close();
                return result;
            });

            // 删除所有匹配的键
            if (!CollectionUtils.isEmpty(keys)) {
                redisBlockService.deleteObject(keys);
                log.info("清空了{}个模板缓存", keys.size());
            }
        } catch (Exception e) {
            log.error("清空模板缓存时发生错误", e);
        }
    }
}